<?php

namespace app\common\model;

use helper\Auth;
use think\exception\HttpException;
use think\facade\Db;
use think\facade\Session;

class User extends Base
{
    // 设置字段信息
//    protected $schema = [
//        'id'          => 'int',
//        'user_type'   => 'int',
//        'username'    => 'string',
//        'name'        => 'string',
//        'status'      => 'int',
//        'score'       => 'float',
//        'create_time' => 'datetime',
//        'update_time' => 'datetime',
//    ];

    public function getGenderAttr($value): string
    {
        $status = [0=>'保密', 1=>'男', 2=>'女'];
        return $status[$value];
    }

    public function getUserStatusAttr($value): string
    {
        $status = [0=>'禁用', 1=>'正常', 2=>'未验证'];
        return $status[$value];
    }

    public function setPasswordAttr($value)
    {
        return password_hash($value, PASSWORD_DEFAULT);
    }

    // 多对多
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }

    // 一对多
    public function comments()
    {
        return $this->hasMany(Comment::class, 'user_id');
    }

    /**
     * 添加管理员
     * @param array $data
     * @return bool
     */
    public static function assignAdmin(array $data): bool
    {
        // 开启事务
        $result = true;
        self::startTrans();
        try {
            $data['user_type'] = 1;
            $user = self::create($data);
            $user->roles()->saveAll($data['role_id']);
            // 提交事务
            self::commit();
        } catch (HttpException $e){
            // 事务回滚
            $result = false;
            self::rollback();
        }
        return $result;
    }

    /**
     * 更新管理员
     * @param array $data
     * @return bool
     */
    public static function syncAdmin(array $data)
    {
        // 开启事务
        $result = true;
        self::startTrans();
        try {
            $user = self::update($data);
            $user->roles()->detach();
            $user->roles()->saveAll($data['role_id']);
            // 提交事务
            self::commit();
        } catch (HttpException $e){
            // 事务回滚
            $result = false;
            self::rollback();
        }
        return $result;
    }

    /**
     * 删除管理员
     * @param $id
     * @return bool
     */
    public static function removeAdmin($id)
    {
        // 开启事务
        $result = true;
        self::startTrans();
        try {
            $user = User::find($id);
            $user->delete();
            $user->roles()->detach();
            // 提交事务
            self::commit();
        } catch (HttpException $e){
            // 事务回滚
            $result = false;
            self::rollback();
        }
        return $result;
    }

    public function syncScore($user_id, $score)
    {
        Db::name('users')
            ->where('id', $user_id)
            ->dec('score', $score)
            ->update();

        $data = ['user_id' => $user_id, 'score' => $score];
        return Db::name('user_score_logs')->insert($data);
    }

    /**
     * 给用户分配权限
     * @param $permission
     */
    public function givePermissionTo($permission)
    {

    }

    public function revokePermissionTo()
    {

    }

    public function syncPermissions($permission)
    {

    }

    /**
     * 检查权限
     * @param string $permission
     */
    public static function hasPermission($permission, $uid = '', $relation = 'or')
    {
        $authList = self::getPermission($uid);//获取用户需要验证的所有有效规则列表
        if (is_string($permission)) {
            $permission = strtolower($permission);
            if (strpos($permission, ',') !== false) {
                $permission = explode(',', $permission);
            } else {
                $permission = [$permission];
            }
        }
        $list = [];//保存验证通过的规则名
        $REQUEST = unserialize(strtolower(serialize($_REQUEST)));
        foreach ($authList as $auth) {
            $query = preg_replace('/^.+\?/U', '', $auth);
            if ($query != $auth) {
                // 解析规则中的param
                parse_str($query, $param);
                $intersect = array_intersect_assoc($REQUEST, $param);
                $auth = preg_replace('/\?.*$/U', '', $auth);
                //如果节点相符且url参数满足
                if (in_array($auth, $permission) && $intersect == $param) {
                    $list[] = $auth;
                }
            } elseif (in_array($auth, $permission)) {
                $list[] = $auth;
            }
        }
        if ($relation === 'or' && !empty($list)) {
            return true;
        }
        $diff = array_diff($permission, $list);
        if ($relation === 'and' && empty($diff)) {
            return true;
        }
        return false;
    }

    /**
     * 获取用户组权限
     * @param $uid
     * @return array|mixed
     */
    public static function getPermission($uid)
    {
        //保存用户验证通过的权限列表
        static $permission = [];
        if (isset($permission[$uid])) {
            return $permission[$uid];
        }
        if (Session::has('_AUTH_LIST_' . $uid)) {
            //return Session::get('_AUTH_LIST_' . $uid);
        }
        // 读取用户所属用户组
        $roles = self::getRole($uid);
        // 保存用户所属用户组设置的所有权限规则ID
        $ids = [];
        foreach ($roles as $r) {
            $ids = array_merge($ids, explode(',', trim($r['id'], ',')));
        }
        $ids = array_unique($ids);
        if (empty($ids)) {
            $permission[$uid] = [];
            return [];
        }
        $map = [
            ['role_id', 'in', $ids],
        ];
        // 读取用户组所有权限规则
        $rules = Db::name('role_has_permissions')
            ->alias('rhp')
            ->join('permissions p', 'rhp.permission_id=p.id')
            ->where($map)
            ->column('route');

        // 循环规则
        $permissions = [];
        foreach ($rules as $rule) {
            $permissions[] = strtolower($rule);
        }
        $permission[$uid] = array_unique($permissions);
        Session::set('_AUTH_LIST_' . $uid, $permission[$uid]);
        return $permission[$uid];
    }

    /**
     * 获取用户角色
     * @param int $uid
     * @return array|null
     */
    public static function getRole($uid)
    {
        static $role = [];
        if (isset($role[$uid])) {
            return $role[$uid];
        }
        $roles = Db::name('roles')
            ->field('r.id,r.name,mhr.model_id')
            ->alias('r')
            ->join(['model_has_roles'=>'mhr'],'r.id=mhr.role_id')
            ->where('model_id', $uid)
            ->select();
        $role[$uid] = $roles ?: [];
        return $role[$uid];
    }

    /**
     * 给用户分配角色
     * @param array $param
     * @return int|string
     */
    public static function assignRole(array $param)
    {
        $data = ['model_id' => $param['model_id'], 'model_type' => __CLASS__, 'role_id' => $param['role_id']];
        return Db::name('model_has_roles')->insert($data);
    }

    /**
     * 更新用户角色
     * @param array $param
     * @return int|string
     */
    public static function syncRole(array $param)
    {
        $data = ['model_id' => $param['model_id'], 'model_type' => __CLASS__, 'role_id' => $param['role_id']];
        return Db::name('model_has_roles')->save($data);
    }

    /**
     * 判断用户角色
     * @param int $role_id
     * @return array|null
     */
    public static function hasRole($role_id)
    {
        return Db::name('model_has_roles')->find($role_id);
    }

    /**
     * 删除用户角色
     * @param int $role_id
     * @return int
     */
    public static function removeRole($role_id)
    {
        return Db::name('model_has_roles')->delete($role_id);
    }

    /**
     * 用户余额改变
     * @param array $param
     * @return bool
     */
    public static function change(array $param)
    {
        $user_id  = $param['user_id'];
        $trade_no = $param['trade_no'];
        $amount   = $param['amount'];
        $type     = $param['type'];
        $subject  = $param['subject'] ?? '';
        $remark   = $param['remark'] ?? '';
        $fee      = $param['fee'] ?? 0;

        // 1.用户余额
        $auth = new Auth();
        $user = $auth->retrieveById($user_id);
        $old_money = $user['balance'];
        if ($type) {
            $now_money = $user['balance'] - $amount;
        } else {
            $now_money = $user['balance'] + $amount;
        }
        $auth->syncUser(['id' => $user_id, 'balance' => $now_money]);

        // 2.余额记录
        UserBalanceLog::create([
            'user_id'   => $user_id,
            'out_trade_no' => $trade_no,
            'old_money' => $old_money,
            'money'     => $amount,
            'now_money' => $now_money,
            'fee'       => $fee,
            'payment'   => 4,
            'type'      => $type,
            'subject'   => $subject,
            'remark'    => $remark,
        ]);
        return true;
    }

    /**
     * 用户余额改变
     * @param string $trade_no
     * @return bool
     */
    public static function sysnChange(string $trade_no)
    {
        // 1.查询记录
        $log = UserBalanceLog::where('out_trade_no', $trade_no)->find();
        if ($log['status'] == 1) {
            return false;
        }

        // 2.用户余额
        $auth = new Auth();
        $user = $auth->retrieveById($log->user_id);
        $old_money = $user['balance'];
        $now_money = $user['balance'] + $log['amount'];
        $auth->syncUser(['id' => $log->user_id, 'balance' => $now_money]);

        // 3.余额记录
        $log->old_money = $old_money;
        $log->now_money = $now_money;
        $log->status = 1;
        $log->save();
        return true;
    }
}
